package iwb.reference.cacheaop;

import com.google.common.base.Splitter;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;


@Slf4j
public abstract class AbstractCache<V> {
    public static final String NULL_TEXT = " ";
    public static final String SEPARATOR = "_";
    @Getter
    @Setter
    private Cache<String, V> cache;

    /**
     * initCache.
     */
    @PostConstruct
    public abstract void initCache();

    /**
     * initCacheWithMaximumSizeExpireAfterWrite.
     * @param maximumSize  maximumSize
     * @param time time
     * @param timeUnit timeUnit
     */
    protected void initCacheWithMaximumSizeExpireAfterWrite(int maximumSize, long time, TimeUnit timeUnit) {
        cache =  CacheBuilder.newBuilder()
                .maximumSize(maximumSize)
                .expireAfterWrite(time, timeUnit)
                .build();
    }

    /**
     * initCacheWithMaximumSizeExpireAfterWriteRecordStats .
     * @param maximumSize maximumSize
     * @param time time
     * @param timeUnit timeUnit
     */
    protected void initCacheWithMaximumSizeExpireAfterWriteRecordStats(int maximumSize, long time, TimeUnit timeUnit) {
        cache =  CacheBuilder.newBuilder()
                .recordStats()
                .maximumSize(maximumSize)
                .expireAfterWrite(time, timeUnit)
                .build();
    }





    /**
     *
     * @param target
     * @param key
     * @param atAnnoMethods
     * @return
     */
    protected V setCacheGetCallable(Object target, String key, Method atAnnoMethods,Object[] args) {
        Splitter splitter = Splitter.on(SEPARATOR);
        ArrayList methonArgs = Lists.newArrayList(splitter.split(key));
//        Object[] args = methonArgs.subList(1, methonArgs.size()).stream().toArray();
        try {
            return this.cache.get(key, new Callable<V>() {
                @Override
                public V call() throws Exception {
                    return (V) atAnnoMethods.invoke(target, args);
                }
            });
        } catch (ExecutionException e) {
            log.error("调用方法" + methonArgs.get(0) + "获取cache报错:" + e);
        }
        return null;
    }

}
